/*
 * COPYRIGHT:	2010 Christopher Smith, licenced under the GNU GPL v2; see COPYING in the top level directory
 * PROJECT:		sdedit
 * FILE:		sdedit cstructhelp.c
 * PURPOSE:		incomplete helper functions for manipluating sdedit structures in C
 *				still depends on C++ idioms, only compatible with semi C-style in C++
 */

template <class T> BOOL FORCEINLINE DeleteExistant(T &x)
{
	if(x)
	{
		delete x;
		x = 0;
		return TRUE;
	}
	else
		return FALSE;
}

SID *CopyNewSid(SID const *Src)
{
	if(Src)
	{
		SID *Ret;

		Ret = reinterpret_cast<SID *>(new BYTE[GetLengthSid(const_cast<SID *>(Src))]);
		RtlCopyMemory(Ret, Src, GetLengthSid(const_cast<SID *>(Src)));

		return Ret;
	}
	else
		return NULL;
}

ACL *CopyNewAcl(ACL const *Src)
{
	if(Src)
	{
		ACL *Ret;
		
		Ret = reinterpret_cast<ACL *>(new BYTE[Src->AclSize]);
		RtlCopyMemory(Ret, Src, Src->AclSize);

		return Ret;
	}
	else
		return NULL;
}

void DeleteSdEditStateFields(SD_EDIT_STATE *Src)
{
	if(Src)
	{
		DeleteExistant(Src->Owner.Sid);
		DeleteExistant(Src->Group.Sid);
		DeleteExistant(Src->Dacl.Acl);
		DeleteExistant(Src->Sacl.Acl);
	}
}

void DeleteSdEditState(SD_EDIT_STATE *Src)
{
	if(Src)
	{
		DeleteSdEditStateFields(Src);
		delete Src;
	}
}

SD_EDIT_STATE *CopyNewSdEditState(SD_EDIT_STATE const *Src)
{
	SD_EDIT_STATE *Ret = new SD_EDIT_STATE;
	RtlCopyMemory(Ret, Src, sizeof SD_EDIT_STATE);

	Ret->Owner.Sid = NULL;
	Ret->Group.Sid = NULL;
	Ret->Dacl.Acl = NULL;
	Ret->Sacl.Acl = NULL;

	__try
	{
		if(Src->Owner.Sid)
			Ret->Owner.Sid = CopyNewSid(Src->Owner.Sid);

		if(Src->Group.Sid)
			Ret->Group.Sid = CopyNewSid(Src->Group.Sid);

		if(Src->Dacl.Acl)
			Ret->Dacl.Acl = CopyNewAcl(Src->Dacl.Acl);

		if(Src->Sacl.Acl)
			Ret->Sacl.Acl = CopyNewAcl(Src->Sacl.Acl);
	}
	__finally
	{
		if(abnormal_termination())
			DeleteSdEditState(Ret);
	}

	return Ret;
}

PWSTR CopyNewString(PCWSTR Src)
{
	if(Src)
	{
		PWSTR Ret;
		SIZE_T Length = wcslen(Src) + 1;

		Ret = new WCHAR[Length];
		RtlCopyMemory(Ret, Src, Length * sizeof WCHAR);

		return Ret;
	}
	else
		return NULL;
}